From b9d1a034408647f5e4ac7c00ce3d9b3dae29c954 Mon Sep 17 00:00:00 2001 From: =?utf8?q?S=C3=B8ren=20Sandmann?= Date: Tue, 25 Apr 2006 14:27:32 +0000 Subject: [PATCH] Create 'composited' label. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Tue Apr 25 10:25:28 2006 Søren Sandmann * tests/testgtk.c (create_alpha_window): Create 'composited' label. * tests/testgtk.c (on_composited_changed): New function, change the label to say whether the screen is composited or not. * gtk/gtkwindow.c (gtk_window_on_composited_changed): When composited status change, invalidate the window and propagate the signal;. * gtk/gtkwindow.c (gtk_window_map): Set the appropriate type hint if reset_type_hint is TRUE. * gtk/gtkwindow.c (gtk_window_set_type_hint): If hint is one of the old hints, store a shadow copy in the public window->type_hint bitfield, otherwise set this field to normal. Set the private field to the type hint. * gtk/gtkwindow.c (gtk_window_init): Initialize priv->type_hint. * gtk/gtkwindow.c (struct _GtkWindowPrivate): New field "reset_type_hint" indicating whether the type hint needs to be reset. New field type_hint containing a GdkWindowTypeHint. * gtk/gtkwidget.c (propagate_composited_changed): New function to propagate changes in composited status. (gtk_widget_class_init): Add composited_changed signal. * gtk/gtkwidget.h (struct _GtkWidgetClass): New signal composited-changed. * gtk/gtkwidget.c (gtk_widget_is_composited): New function. * gtk/gtktooltips.c (gtk_tooltips_draw_tips): Set transient for. * gtk/gtktooltips.c (gtk_tooltips_force_window): Set the type hint * gtk/gtkmenuitem.c (gtk_menu_item_position_menu): Compute whether the item belongs to a menubar. Set the type_hint appropriately depending on the outcome. * gtk/gtkmenu.c (gtk_menu_position): Set the default type hint here. * gtk/gtkmenu.c (gtk_menu_attach_to_widget): connect to hierarchy changed on the attach widget. * gtk/gtkmenu.c (attach_widget_hierarchy_changed): New function to set the transient_for property for menus. * gtk/gtkdnd.c (set_icon_stock_pixbuf): Set the appropriate type hint. * gtk/gtkcombo.c (gtk_combo_popup_list): Make the popup window transient for the toplevel. * gtk/gtkcombobox.c (gtk_combo_box_set_popup_widget): Set transient-for, for the popup window. * gdk/x11/gdkwindow-x11.c (gdk_window_get_type_hint): Support for new window types. * gdk/x11/gdkwindow-x11.c (gdk_window_set_type_hint): Add support for new window types. * gdk/x11/gdkscreen-x11.c (_gdk_x11_screen_process_owner_change): New function called whenever the compositing manager comes and goes. * gdk/x11/gdkscreen-x11.c (gdk_screen_is_composited): New function. * gdk/x11/gdkscreen-x11.c (_gdk_x11_screen_request_cm_notification, make_cm_atom, check_is_composited): New functions * gdk/x11/gdkevents-x11.c (gdk_event_translate): Call _gdk_x11_screen_process_owner_change when an XFixesSelectionNotifyEvent is received. * gdk/x11/gdkdisplay-x11.c (gdk_display_open): Call _gdk_x11_screen_request_cm_notification() on all screens. * gdk/quartz/gdkscreen-quartz.c (gdk_screen_is_composited): Dummy implementation. * gdk/gdkscreen.c (gdk_screen_class_init): New signal, 'composited-changed'. * gdk/gdkwindow.h: Add new EWMH window types. * gdk/win32/gdkscreen-win32.c (gdk_screen_is_composited) --- ChangeLog | 89 +++++++++++++++++++++++++++++++++++ ChangeLog.pre-2-10 | 89 +++++++++++++++++++++++++++++++++++ gdk/gdkscreen.c | 20 ++++++++ gdk/gdkscreen.h | 3 +- gdk/gdkwindow.h | 11 +++-- gdk/quartz/gdkscreen-quartz.c | 8 ++++ gdk/win32/gdkscreen-win32.c | 8 ++++ gdk/x11/gdkdisplay-x11.c | 9 +++- gdk/x11/gdkevents-x11.c | 5 +- gdk/x11/gdkscreen-x11.c | 85 ++++++++++++++++++++++++++++++++- gdk/x11/gdkscreen-x11.h | 5 ++ gdk/x11/gdkwindow-x11.c | 30 ++++++++++++ gtk/gtkcombo.c | 2 + gtk/gtkcombobox.c | 11 ++++- gtk/gtkdnd.c | 2 + gtk/gtkmenu.c | 40 +++++++++++++++- gtk/gtkmenuitem.c | 42 ++++++++++++++--- gtk/gtkmenuitem.h | 1 + gtk/gtktooltips.c | 6 +++ gtk/gtkwidget.c | 52 ++++++++++++++++++++ gtk/gtkwidget.h | 7 ++- gtk/gtkwindow.c | 74 +++++++++++++++++++++++++---- gtk/gtkwindow.h | 4 +- tests/testgtk.c | 29 +++++++++--- 24 files changed, 598 insertions(+), 34 deletions(-) diff --git a/ChangeLog b/ChangeLog index ef2b50008f..27345cf57b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,91 @@ +Tue Apr 25 10:25:28 2006 Søren Sandmann + + * tests/testgtk.c (create_alpha_window): Create 'composited' label. + + * tests/testgtk.c (on_composited_changed): New function, change + the label to say whether the screen is composited or not. + + * gtk/gtkwindow.c (gtk_window_on_composited_changed): When + composited status change, invalidate the window and propagate the signal;. + + * gtk/gtkwindow.c (gtk_window_map): Set the appropriate type hint + if reset_type_hint is TRUE. + + * gtk/gtkwindow.c (gtk_window_set_type_hint): If hint is one of + the old hints, store a shadow copy in the public window->type_hint + bitfield, otherwise set this field to normal. Set the private + field to the type hint. + + * gtk/gtkwindow.c (gtk_window_init): Initialize priv->type_hint. + + * gtk/gtkwindow.c (struct _GtkWindowPrivate): New field + "reset_type_hint" indicating whether the type hint needs to be + reset. New field type_hint containing a GdkWindowTypeHint. + + * gtk/gtkwidget.c (propagate_composited_changed): New function to + propagate changes in composited status. + (gtk_widget_class_init): Add composited_changed signal. + + * gtk/gtkwidget.h (struct _GtkWidgetClass): New signal composited-changed. + + * gtk/gtkwidget.c (gtk_widget_is_composited): New function. + + * gtk/gtktooltips.c (gtk_tooltips_draw_tips): Set transient for. + + * gtk/gtktooltips.c (gtk_tooltips_force_window): Set the type hint + + * gtk/gtkmenuitem.c (gtk_menu_item_position_menu): Compute whether + the item belongs to a menubar. Set the type_hint appropriately + depending on the outcome. + + * gtk/gtkmenu.c (gtk_menu_position): Set the default type hint here. + + * gtk/gtkmenu.c (gtk_menu_attach_to_widget): connect to hierarchy + changed on the attach widget. + + * gtk/gtkmenu.c (attach_widget_hierarchy_changed): New function to + set the transient_for property for menus. + + * gtk/gtkdnd.c (set_icon_stock_pixbuf): Set the appropriate type hint. + + * gtk/gtkcombo.c (gtk_combo_popup_list): Make the popup window + transient for the toplevel. + + * gtk/gtkcombobox.c (gtk_combo_box_set_popup_widget): Set + transient-for, for the popup window. + + * gdk/x11/gdkwindow-x11.c (gdk_window_get_type_hint): Support for + new window types. + + * gdk/x11/gdkwindow-x11.c (gdk_window_set_type_hint): Add support + for new window types. + + * gdk/x11/gdkscreen-x11.c (_gdk_x11_screen_process_owner_change): + New function called whenever the compositing manager comes and goes. + + * gdk/x11/gdkscreen-x11.c (gdk_screen_is_composited): New function. + + * gdk/x11/gdkscreen-x11.c + (_gdk_x11_screen_request_cm_notification, make_cm_atom, + check_is_composited): New functions + + * gdk/x11/gdkevents-x11.c (gdk_event_translate): Call + _gdk_x11_screen_process_owner_change when an + XFixesSelectionNotifyEvent is received. + + * gdk/x11/gdkdisplay-x11.c (gdk_display_open): Call + _gdk_x11_screen_request_cm_notification() on all screens. + + * gdk/quartz/gdkscreen-quartz.c (gdk_screen_is_composited): Dummy + implementation. + + * gdk/gdkscreen.c (gdk_screen_class_init): New signal, + 'composited-changed'. + + * gdk/gdkwindow.h: Add new EWMH window types. + + * gdk/win32/gdkscreen-win32.c (gdk_screen_is_composited) + 2006-04-25 Matthias Clasen * modules/printbackends/cups/gtkprintbackendcups.c: @@ -40,6 +128,7 @@ * gtk/gtkprinter.c: Don't ref the backend since the backend owns the printer. +>>>>>>> 1.7779 2006-04-24 Alexander Larsson * gtk/gtkpagesetupunixdialog.c (update_combo_sensitivity_from_printers): diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index ef2b50008f..27345cf57b 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,91 @@ +Tue Apr 25 10:25:28 2006 Søren Sandmann + + * tests/testgtk.c (create_alpha_window): Create 'composited' label. + + * tests/testgtk.c (on_composited_changed): New function, change + the label to say whether the screen is composited or not. + + * gtk/gtkwindow.c (gtk_window_on_composited_changed): When + composited status change, invalidate the window and propagate the signal;. + + * gtk/gtkwindow.c (gtk_window_map): Set the appropriate type hint + if reset_type_hint is TRUE. + + * gtk/gtkwindow.c (gtk_window_set_type_hint): If hint is one of + the old hints, store a shadow copy in the public window->type_hint + bitfield, otherwise set this field to normal. Set the private + field to the type hint. + + * gtk/gtkwindow.c (gtk_window_init): Initialize priv->type_hint. + + * gtk/gtkwindow.c (struct _GtkWindowPrivate): New field + "reset_type_hint" indicating whether the type hint needs to be + reset. New field type_hint containing a GdkWindowTypeHint. + + * gtk/gtkwidget.c (propagate_composited_changed): New function to + propagate changes in composited status. + (gtk_widget_class_init): Add composited_changed signal. + + * gtk/gtkwidget.h (struct _GtkWidgetClass): New signal composited-changed. + + * gtk/gtkwidget.c (gtk_widget_is_composited): New function. + + * gtk/gtktooltips.c (gtk_tooltips_draw_tips): Set transient for. + + * gtk/gtktooltips.c (gtk_tooltips_force_window): Set the type hint + + * gtk/gtkmenuitem.c (gtk_menu_item_position_menu): Compute whether + the item belongs to a menubar. Set the type_hint appropriately + depending on the outcome. + + * gtk/gtkmenu.c (gtk_menu_position): Set the default type hint here. + + * gtk/gtkmenu.c (gtk_menu_attach_to_widget): connect to hierarchy + changed on the attach widget. + + * gtk/gtkmenu.c (attach_widget_hierarchy_changed): New function to + set the transient_for property for menus. + + * gtk/gtkdnd.c (set_icon_stock_pixbuf): Set the appropriate type hint. + + * gtk/gtkcombo.c (gtk_combo_popup_list): Make the popup window + transient for the toplevel. + + * gtk/gtkcombobox.c (gtk_combo_box_set_popup_widget): Set + transient-for, for the popup window. + + * gdk/x11/gdkwindow-x11.c (gdk_window_get_type_hint): Support for + new window types. + + * gdk/x11/gdkwindow-x11.c (gdk_window_set_type_hint): Add support + for new window types. + + * gdk/x11/gdkscreen-x11.c (_gdk_x11_screen_process_owner_change): + New function called whenever the compositing manager comes and goes. + + * gdk/x11/gdkscreen-x11.c (gdk_screen_is_composited): New function. + + * gdk/x11/gdkscreen-x11.c + (_gdk_x11_screen_request_cm_notification, make_cm_atom, + check_is_composited): New functions + + * gdk/x11/gdkevents-x11.c (gdk_event_translate): Call + _gdk_x11_screen_process_owner_change when an + XFixesSelectionNotifyEvent is received. + + * gdk/x11/gdkdisplay-x11.c (gdk_display_open): Call + _gdk_x11_screen_request_cm_notification() on all screens. + + * gdk/quartz/gdkscreen-quartz.c (gdk_screen_is_composited): Dummy + implementation. + + * gdk/gdkscreen.c (gdk_screen_class_init): New signal, + 'composited-changed'. + + * gdk/gdkwindow.h: Add new EWMH window types. + + * gdk/win32/gdkscreen-win32.c (gdk_screen_is_composited) + 2006-04-25 Matthias Clasen * modules/printbackends/cups/gtkprintbackendcups.c: @@ -40,6 +128,7 @@ * gtk/gtkprinter.c: Don't ref the backend since the backend owns the printer. +>>>>>>> 1.7779 2006-04-24 Alexander Larsson * gtk/gtkpagesetupunixdialog.c (update_combo_sensitivity_from_printers): diff --git a/gdk/gdkscreen.c b/gdk/gdkscreen.c index 6f531a96f0..924ef531d0 100644 --- a/gdk/gdkscreen.c +++ b/gdk/gdkscreen.c @@ -50,6 +50,7 @@ enum enum { SIZE_CHANGED, + COMPOSITED_CHANGED, LAST_SIGNAL }; @@ -104,6 +105,25 @@ gdk_screen_class_init (GdkScreenClass *klass) g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + /** + * GdkScreen::composited-changed: + * @screen: the object on which the signal is emitted + * + * The ::composited_changed signal is emitted when the composited + * status of the screen changes + * + * Since: 2.10 + */ + signals[COMPOSITED_CHANGED] = + g_signal_new (g_intern_static_string ("composited_changed"), + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GdkScreenClass, composited_changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); } static void diff --git a/gdk/gdkscreen.h b/gdk/gdkscreen.h index 3b6624b687..7ff920193f 100644 --- a/gdk/gdkscreen.h +++ b/gdk/gdkscreen.h @@ -57,6 +57,7 @@ struct _GdkScreenClass GObjectClass parent_class; void (*size_changed) (GdkScreen *screen); + void (*composited_changed) (GdkScreen *screen); }; GType gdk_screen_get_type (void) G_GNUC_CONST; @@ -69,7 +70,7 @@ GdkColormap *gdk_screen_get_rgb_colormap (GdkScreen *screen); GdkVisual * gdk_screen_get_rgb_visual (GdkScreen *screen); GdkColormap *gdk_screen_get_rgba_colormap (GdkScreen *screen); GdkVisual * gdk_screen_get_rgba_visual (GdkScreen *screen); - +gboolean gdk_screen_is_composited (GdkScreen *screen); GdkWindow * gdk_screen_get_root_window (GdkScreen *screen); GdkDisplay * gdk_screen_get_display (GdkScreen *screen); diff --git a/gdk/gdkwindow.h b/gdk/gdkwindow.h index 4ff4847e16..b0962bcfde 100644 --- a/gdk/gdkwindow.h +++ b/gdk/gdkwindow.h @@ -127,15 +127,20 @@ typedef enum { GDK_WINDOW_TYPE_HINT_NORMAL, GDK_WINDOW_TYPE_HINT_DIALOG, - GDK_WINDOW_TYPE_HINT_MENU, + GDK_WINDOW_TYPE_HINT_MENU, /* Torn off menu */ GDK_WINDOW_TYPE_HINT_TOOLBAR, GDK_WINDOW_TYPE_HINT_SPLASHSCREEN, GDK_WINDOW_TYPE_HINT_UTILITY, GDK_WINDOW_TYPE_HINT_DOCK, - GDK_WINDOW_TYPE_HINT_DESKTOP + GDK_WINDOW_TYPE_HINT_DESKTOP, + GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU, /* A drop down menu (from a menubar) */ + GDK_WINDOW_TYPE_HINT_POPUP_MENU, /* A popup menu (from right-click) */ + GDK_WINDOW_TYPE_HINT_TOOLTIP, + GDK_WINDOW_TYPE_HINT_NOTIFICATION, + GDK_WINDOW_TYPE_HINT_COMBO, + GDK_WINDOW_TYPE_HINT_DND } GdkWindowTypeHint; - /* The next two enumeration values current match the * Motif constants. If this is changed, the implementation * of gdk_window_set_decorations/gdk_window_set_functions diff --git a/gdk/quartz/gdkscreen-quartz.c b/gdk/quartz/gdkscreen-quartz.c index 3aadebd063..c1484256fa 100644 --- a/gdk/quartz/gdkscreen-quartz.c +++ b/gdk/quartz/gdkscreen-quartz.c @@ -255,3 +255,11 @@ gdk_screen_get_window_stack (GdkScreen *screen) return NULL; } + +gboolean +gdk_screen_is_composited (GdkScreen *screen) +{ + g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE); + + return TRUE; +} diff --git a/gdk/win32/gdkscreen-win32.c b/gdk/win32/gdkscreen-win32.c index 0bf47e3dcf..ea16a64046 100644 --- a/gdk/win32/gdkscreen-win32.c +++ b/gdk/win32/gdkscreen-win32.c @@ -133,3 +133,11 @@ gdk_screen_get_window_stack (GdkScreen *screen) return NULL; } + +gboolean +gdk_screen_is_composited (GdkScreen *screen) +{ + g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE); + + return FALSE; +} diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c index e082500b4b..6034379c09 100644 --- a/gdk/x11/gdkdisplay-x11.c +++ b/gdk/x11/gdkdisplay-x11.c @@ -77,6 +77,7 @@ static const char *const precache_atoms[] = { "WM_LOCALE_NAME", "WM_PROTOCOLS", "WM_TAKE_FOCUS", + "_NET_WM_CM_S0", "_NET_WM_DESKTOP", "_NET_WM_ICON", "_NET_WM_ICON_NAME", @@ -311,6 +312,9 @@ gdk_display_open (const gchar *display_name) _gdk_input_init (display); _gdk_dnd_init (display); + for (i = 0; i < ScreenCount (display_x11->xdisplay); i++) + _gdk_x11_screen_request_cm_notification (display_x11->screens[i]); + g_signal_emit_by_name (gdk_display_manager_get(), "display_opened", display); @@ -1102,8 +1106,9 @@ gdk_display_supports_selection_notification (GdkDisplay *display) * * Since: 2.6 **/ -gboolean gdk_display_request_selection_notification (GdkDisplay *display, - GdkAtom selection) +gboolean +gdk_display_request_selection_notification (GdkDisplay *display, + GdkAtom selection) { #ifdef HAVE_XFIXES diff --git a/gdk/x11/gdkevents-x11.c b/gdk/x11/gdkevents-x11.c index 40bce56b30..46cdd12857 100644 --- a/gdk/x11/gdkevents-x11.c +++ b/gdk/x11/gdkevents-x11.c @@ -2077,6 +2077,9 @@ gdk_event_translate (GdkDisplay *display, if (xevent->type - display_x11->xfixes_event_base == XFixesSelectionNotify) { XFixesSelectionNotifyEvent *selection_notify = (XFixesSelectionNotifyEvent *)xevent; + + _gdk_x11_screen_process_owner_change (screen, xevent); + event->owner_change.type = GDK_OWNER_CHANGE; event->owner_change.window = window; event->owner_change.owner = selection_notify->owner; @@ -2086,7 +2089,7 @@ gdk_event_translate (GdkDisplay *display, selection_notify->selection); event->owner_change.time = selection_notify->timestamp; event->owner_change.selection_time = selection_notify->selection_timestamp; - + return_val = TRUE; } else diff --git a/gdk/x11/gdkscreen-x11.c b/gdk/x11/gdkscreen-x11.c index 3efb0559d5..70e623a5a0 100644 --- a/gdk/x11/gdkscreen-x11.c +++ b/gdk/x11/gdkscreen-x11.c @@ -47,6 +47,10 @@ #include #endif +#ifdef HAVE_XFIXES +#include +#endif + static void gdk_screen_x11_dispose (GObject *object); static void gdk_screen_x11_finalize (GObject *object); static void init_xinerama_support (GdkScreen *screen); @@ -460,6 +464,27 @@ gdk_x11_screen_get_screen_number (GdkScreen *screen) return GDK_SCREEN_X11 (screen)->screen_num; } +static gboolean +check_is_composited (GdkDisplay *display, + GdkScreenX11 *screen_x11) +{ + Atom xselection = gdk_x11_atom_to_xatom_for_display (display, screen_x11->cm_selection_atom); + Window xwindow; + + xwindow = XGetSelectionOwner (GDK_DISPLAY_XDISPLAY (display), xselection); + + return xwindow != None; +} + +static GdkAtom +make_cm_atom (int screen_number) +{ + gchar *name = g_strdup_printf ("_NET_WM_CM_S%d", screen_number); + GdkAtom atom = gdk_atom_intern (name, FALSE); + g_free (name); + return atom; +} + GdkScreen * _gdk_x11_screen_new (GdkDisplay *display, gint screen_number) @@ -479,16 +504,52 @@ _gdk_x11_screen_new (GdkDisplay *display, screen_x11->wmspec_check_window = None; /* we want this to be always non-null */ screen_x11->window_manager_name = g_strdup ("unknown"); + screen_x11->cm_selection_atom = make_cm_atom (screen_number); + screen_x11->is_composited = check_is_composited (display, screen_x11); init_xinerama_support (screen); init_randr_support (screen); _gdk_visual_init (screen); _gdk_windowing_window_init (screen); - + return screen; } +void +_gdk_x11_screen_request_cm_notification (GdkScreenX11 *screen_x11) +{ + gdk_display_request_selection_notification (screen_x11->display, screen_x11->cm_selection_atom); +} + +/** + * gdk_screen_is_composited: + * @screen: a #GdkScreen + * + * Returns whether windows with an RGBA visual can reasonably + * be expected to have their alpha channel drawn correctly on + * the screen. + * + * On X11 this function returns whether a compositing manager is + * compositing @screen. + * + * Return value: Whether windows with RGBA visuals can reasonably be + * expected to have their alpha channels drawn correctly on the screen. + * + * Since: 2.10 + **/ +gboolean +gdk_screen_is_composited (GdkScreen *screen) +{ + GdkScreenX11 *screen_x11; + + g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE); + + screen_x11 = GDK_SCREEN_X11 (screen); + + return screen_x11->is_composited; +} + #ifdef HAVE_XINERAMA static gboolean check_solaris_xinerama (GdkScreen *screen) @@ -705,6 +766,28 @@ _gdk_x11_screen_window_manager_changed (GdkScreen *screen) g_signal_emit (screen, signals[WINDOW_MANAGER_CHANGED], 0); } +void +_gdk_x11_screen_process_owner_change (GdkScreen *screen, + XEvent *event) +{ + XFixesSelectionNotifyEvent *selection_event = (XFixesSelectionNotifyEvent *)event; + GdkScreenX11 *screen_x11 = GDK_SCREEN_X11 (screen); + Atom xcm_selection_atom = gdk_x11_atom_to_xatom_for_display (screen_x11->display, + screen_x11->cm_selection_atom); + + if (selection_event->selection == xcm_selection_atom) + { + gboolean composited = selection_event->owner != None; + + if (composited != screen_x11->is_composited) + { + screen_x11->is_composited = composited; + + g_signal_emit_by_name (screen, "composited_changed"); + } + } +} + /** * _gdk_windowing_substitute_screen_number: * @display_name : The name of a display, in the form used by diff --git a/gdk/x11/gdkscreen-x11.h b/gdk/x11/gdkscreen-x11.h index 5ea82a4fbc..6ba8d62999 100644 --- a/gdk/x11/gdkscreen-x11.h +++ b/gdk/x11/gdkscreen-x11.h @@ -103,6 +103,9 @@ struct _GdkScreenX11 gint xft_hintstyle; gint xft_rgba; gint xft_dpi; + + GdkAtom cm_selection_atom; + gboolean is_composited; }; struct _GdkScreenX11Class @@ -119,6 +122,8 @@ GdkScreen * _gdk_x11_screen_new (GdkDisplay *display, void _gdk_x11_screen_window_manager_changed (GdkScreen *screen); void _gdk_x11_screen_size_changed (GdkScreen *screen, XEvent *event); +void _gdk_x11_screen_process_owner_change (GdkScreen *screen, + XEvent *event); G_END_DECLS diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c index 384711ce4f..52a85c71ee 100644 --- a/gdk/x11/gdkwindow-x11.c +++ b/gdk/x11/gdkwindow-x11.c @@ -2226,6 +2226,24 @@ gdk_window_set_type_hint (GdkWindow *window, case GDK_WINDOW_TYPE_HINT_DESKTOP: atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP"); break; + case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU: + atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"); + break; + case GDK_WINDOW_TYPE_HINT_POPUP_MENU: + atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_POPUP_MENU"); + break; + case GDK_WINDOW_TYPE_HINT_TOOLTIP: + atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLTIP"); + break; + case GDK_WINDOW_TYPE_HINT_NOTIFICATION: + atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NOTIFICATION"); + break; + case GDK_WINDOW_TYPE_HINT_COMBO: + atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_COMBO"); + break; + case GDK_WINDOW_TYPE_HINT_DND: + atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DND"); + break; default: g_warning ("Unknown hint %d passed to gdk_window_set_type_hint", hint); /* Fall thru */ @@ -2295,6 +2313,18 @@ gdk_window_get_type_hint (GdkWindow *window) type = GDK_WINDOW_TYPE_HINT_DOCK; else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP")) type = GDK_WINDOW_TYPE_HINT_DESKTOP; + else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU")) + type = GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU; + else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_POPUP_MENU")) + type = GDK_WINDOW_TYPE_HINT_POPUP_MENU; + else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLTIP")) + type = GDK_WINDOW_TYPE_HINT_TOOLTIP; + else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NOTIFICATION")) + type = GDK_WINDOW_TYPE_HINT_NOTIFICATION; + else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_COMBO")) + type = GDK_WINDOW_TYPE_HINT_COMBO; + else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DND")) + type = GDK_WINDOW_TYPE_HINT_DND; } if (type_return != None && data != NULL) diff --git a/gtk/gtkcombo.c b/gtk/gtkcombo.c index a5b7b17a7c..345780f39a 100644 --- a/gtk/gtkcombo.c +++ b/gtk/gtkcombo.c @@ -564,6 +564,7 @@ gtk_combo_popup_list (GtkCombo *combo) { gtk_window_group_add_window (gtk_window_get_group (GTK_WINDOW (toplevel)), GTK_WINDOW (combo->popwin)); + gtk_window_set_transient_for (combo->popwin, GTK_WINDOW (toplevel)); } gtk_widget_set_size_request (combo->popwin, width, height); @@ -941,6 +942,7 @@ gtk_combo_init (GtkCombo * combo) G_CALLBACK (gtk_combo_popup_button_leave), combo); combo->popwin = gtk_window_new (GTK_WINDOW_POPUP); + gtk_window_set_type_hint (GTK_WINDOW (combo->popwin), GDK_WINDOW_TYPE_HINT_COMBO); g_object_ref (combo->popwin); gtk_window_set_resizable (GTK_WINDOW (combo->popwin), FALSE); diff --git a/gtk/gtkcombobox.c b/gtk/gtkcombobox.c index eb730a5b87..640661aa90 100644 --- a/gtk/gtkcombobox.c +++ b/gtk/gtkcombobox.c @@ -1220,6 +1220,9 @@ gtk_combo_box_set_popup_widget (GtkComboBox *combo_box, combo_box->priv->popup_window = gtk_window_new (GTK_WINDOW_POPUP); + gtk_window_set_type_hint (GTK_WINDOW (combo_box->priv->popup_window), + GDK_WINDOW_TYPE_HINT_COMBO); + g_signal_connect (GTK_WINDOW(combo_box->priv->popup_window),"show", G_CALLBACK (gtk_combo_box_child_show), combo_box); @@ -1229,8 +1232,12 @@ gtk_combo_box_set_popup_widget (GtkComboBox *combo_box, toplevel = gtk_widget_get_toplevel (GTK_WIDGET (combo_box)); if (GTK_IS_WINDOW (toplevel)) - gtk_window_group_add_window (gtk_window_get_group (GTK_WINDOW (toplevel)), - GTK_WINDOW (combo_box->priv->popup_window)); + { + gtk_window_group_add_window (gtk_window_get_group (GTK_WINDOW (toplevel)), + GTK_WINDOW (combo_box->priv->popup_window)); + gtk_window_set_transient_for (GTK_WINDOW (combo_box->priv->popup_window), + GTK_WINDOW (toplevel)); + } gtk_window_set_resizable (GTK_WINDOW (combo_box->priv->popup_window), FALSE); gtk_window_set_screen (GTK_WINDOW (combo_box->priv->popup_window), diff --git a/gtk/gtkdnd.c b/gtk/gtkdnd.c index c7aeea1806..8c2d2abc76 100644 --- a/gtk/gtkdnd.c +++ b/gtk/gtkdnd.c @@ -2938,6 +2938,7 @@ set_icon_stock_pixbuf (GdkDragContext *context, /* Push a NULL colormap to guard against gtk_widget_push_colormap() */ gtk_widget_push_colormap (NULL); window = gtk_window_new (GTK_WINDOW_POPUP); + gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_DND); gtk_window_set_screen (GTK_WINDOW (window), screen); set_can_change_screen (window, TRUE); gtk_widget_pop_colormap (); @@ -3083,6 +3084,7 @@ gtk_drag_set_icon_pixmap (GdkDragContext *context, gtk_widget_push_colormap (colormap); window = gtk_window_new (GTK_WINDOW_POPUP); + gtk_window_set_type_hint (window, GDK_WINDOW_TYPE_HINT_DND); gtk_window_set_screen (GTK_WINDOW (window), screen); set_can_change_screen (window, FALSE); gtk_widget_set_events (window, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); diff --git a/gtk/gtkmenu.c b/gtk/gtkmenu.c index cb406b2680..68d1e71a52 100644 --- a/gtk/gtkmenu.c +++ b/gtk/gtkmenu.c @@ -1036,6 +1036,33 @@ attach_widget_screen_changed (GtkWidget *attach_widget, } } +static void +attach_widget_hierarchy_changed (GtkWidget *attach_widget, + GtkWidget *previous_toplevel, + gpointer data) +{ + GtkMenu *menu = GTK_MENU (data); + GtkWidget *new_toplevel = gtk_widget_get_toplevel (attach_widget); + + if (g_object_get_data (G_OBJECT (menu), "gtk-menu-explicit-screen")) + { + /* If there is an explicit screen set, then don't set WM_TRANSIENT_FOR. + * Because, what would happen if the attach widget moved to a different + * screen on a different display? The menu wouldn't move along with it, + * so we just make it the responsibility of whoever set the screen to + * also set WM_TRANSIENT_FOR. + */ + return; + } + + if (menu->toplevel && !g_object_get_data (G_OBJECT (menu), "gtk-menu-explicit-screen") && + (!new_toplevel || GTK_IS_WINDOW (new_toplevel))) + { + gtk_window_set_transient_for (GTK_WINDOW (menu->toplevel), + GTK_WINDOW (new_toplevel)); + } +} + void gtk_menu_attach_to_widget (GtkMenu *menu, GtkWidget *attach_widget, @@ -1067,6 +1094,10 @@ gtk_menu_attach_to_widget (GtkMenu *menu, G_CALLBACK (attach_widget_screen_changed), menu); attach_widget_screen_changed (attach_widget, NULL, menu); + g_signal_connect (attach_widget, "hierarchy_changed", + G_CALLBACK (attach_widget_hierarchy_changed), menu); + attach_widget_hierarchy_changed (attach_widget, NULL, menu); + data->detacher = detacher; g_object_set_data (G_OBJECT (menu), I_(attach_data_key), data); list = g_object_steal_data (G_OBJECT (attach_widget), ATTACHED_MENUS); @@ -1121,6 +1152,10 @@ gtk_menu_detach (GtkMenu *menu) g_signal_handlers_disconnect_by_func (data->attach_widget, (gpointer) attach_widget_screen_changed, menu); + g_signal_handlers_disconnect_by_func (data->attach_widget, + (gpointer) attach_widget_hierarchy_changed, + menu); + attach_widget_hierarchy_changed (data->attach_widget, NULL, menu); if (data->detacher) data->detacher (data->attach_widget, menu); @@ -1836,7 +1871,6 @@ gtk_menu_set_tearoff_state (GtkMenu *menu, "app-paintable", TRUE, NULL); - gtk_window_set_type_hint (GTK_WINDOW (menu->tearoff_window), GDK_WINDOW_TYPE_HINT_MENU); gtk_window_set_mnemonic_modifier (GTK_WINDOW (menu->tearoff_window), 0); @@ -3765,6 +3799,10 @@ gtk_menu_position (GtkMenu *menu) private->monitor_num = gdk_screen_get_monitor_at_point (screen, x, y); private->initially_pushed_in = FALSE; + + /* Set the type hint here to allow custom position functions to set a different hint */ + if (!GTK_WIDGET_VISIBLE (menu->toplevel)) + gtk_window_set_type_hint (GTK_WINDOW (menu->toplevel), GDK_WINDOW_TYPE_HINT_POPUP_MENU); if (menu->position_func) { diff --git a/gtk/gtkmenuitem.c b/gtk/gtkmenuitem.c index b58e13612e..3b3d346c59 100644 --- a/gtk/gtkmenuitem.c +++ b/gtk/gtkmenuitem.c @@ -1122,7 +1122,7 @@ gtk_menu_item_position_menu (GtkMenu *menu, { GtkMenuItem *menu_item; GtkWidget *widget; - GtkWidget *parent_menu_item; + GtkMenuItem *parent_menu_item; GdkScreen *screen; gint twidth, theight; gint tx, ty; @@ -1164,6 +1164,22 @@ gtk_menu_item_position_menu (GtkMenu *menu, ty += widget->allocation.y; get_offsets (menu, &horizontal_offset, &vertical_offset); + + if (GTK_IS_MENU_BAR (widget->parent)) + { + menu_item->from_menubar = TRUE; + } + else if (GTK_IS_MENU (widget->parent)) + { + if (GTK_MENU (widget->parent)->parent_menu_item) + menu_item->from_menubar = GTK_MENU_ITEM (GTK_MENU (widget->parent)->parent_menu_item)->from_menubar; + else + menu_item->from_menubar = FALSE; + } + else + { + menu_item->from_menubar = FALSE; + } switch (menu_item->submenu_placement) { @@ -1175,7 +1191,6 @@ gtk_menu_item_position_menu (GtkMenu *menu, menu_item->submenu_direction = GTK_DIRECTION_LEFT; tx += widget->allocation.width - twidth; } - if ((ty + widget->allocation.height + theight) <= monitor.y + monitor.height) ty += widget->allocation.height; else if ((ty - theight) >= monitor.y) @@ -1188,16 +1203,23 @@ gtk_menu_item_position_menu (GtkMenu *menu, case GTK_LEFT_RIGHT: if (GTK_IS_MENU (widget->parent)) - parent_menu_item = GTK_MENU (widget->parent)->parent_menu_item; + parent_menu_item = GTK_MENU_ITEM (GTK_MENU (widget->parent)->parent_menu_item); else parent_menu_item = NULL; + parent_xthickness = widget->parent->style->xthickness; + if (parent_menu_item && !GTK_MENU (widget->parent)->torn_off) - menu_item->submenu_direction = GTK_MENU_ITEM (parent_menu_item)->submenu_direction; - else if (direction == GTK_TEXT_DIR_LTR) - menu_item->submenu_direction = GTK_DIRECTION_RIGHT; + { + menu_item->submenu_direction = parent_menu_item->submenu_direction; + } else - menu_item->submenu_direction = GTK_DIRECTION_LEFT; + { + if (direction == GTK_TEXT_DIR_LTR) + menu_item->submenu_direction = GTK_DIRECTION_RIGHT; + else + menu_item->submenu_direction = GTK_DIRECTION_LEFT; + } switch (menu_item->submenu_direction) { @@ -1236,6 +1258,12 @@ gtk_menu_item_position_menu (GtkMenu *menu, *y = ty; gtk_menu_set_monitor (menu, monitor_num); + + if (!GTK_WIDGET_VISIBLE (menu->toplevel)) + { + gtk_window_set_type_hint (GTK_WINDOW (menu->toplevel), menu_item->from_menubar? + GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU : GDK_WINDOW_TYPE_HINT_POPUP_MENU); + } } /** diff --git a/gtk/gtkmenuitem.h b/gtk/gtkmenuitem.h index 0d7a42e9de..e76087b601 100644 --- a/gtk/gtkmenuitem.h +++ b/gtk/gtkmenuitem.h @@ -61,6 +61,7 @@ struct _GtkMenuItem guint submenu_direction : 1; guint right_justify: 1; guint timer_from_keypress : 1; + guint from_menubar : 1; guint timer; }; diff --git a/gtk/gtktooltips.c b/gtk/gtktooltips.c index ed505915ce..be47d73036 100644 --- a/gtk/gtktooltips.c +++ b/gtk/gtktooltips.c @@ -249,6 +249,7 @@ gtk_tooltips_force_window (GtkTooltips *tooltips) if (!tooltips->tip_window) { tooltips->tip_window = gtk_window_new (GTK_WINDOW_POPUP); + gtk_window_set_type_hint (GTK_WINDOW (tooltips->tip_window), GDK_WINDOW_TYPE_HINT_TOOLTIP); gtk_tooltips_update_screen (tooltips, TRUE); gtk_widget_set_app_paintable (tooltips->tip_window, TRUE); gtk_window_set_resizable (GTK_WINDOW (tooltips->tip_window), FALSE); @@ -405,6 +406,7 @@ gtk_tooltips_draw_tips (GtkTooltips *tooltips) GdkScreen *pointer_screen; gint monitor_num, px, py; GdkRectangle monitor; + GtkWindow *toplevel; if (!tooltips->tip_window) gtk_tooltips_force_window (tooltips); @@ -466,6 +468,10 @@ gtk_tooltips_draw_tips (GtkTooltips *tooltips) else y = y + widget->allocation.height + 4; + toplevel = gtk_widget_get_toplevel (widget); + if (toplevel && GTK_IS_WINDOW (toplevel)) + gtk_window_set_transient_for (tooltips->tip_window, toplevel); + gtk_window_move (GTK_WINDOW (tooltips->tip_window), x, y); gtk_widget_show (tooltips->tip_window); } diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index 194caa0ee2..37747c81d8 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -121,6 +121,7 @@ enum { SCREEN_CHANGED, CAN_ACTIVATE_ACCEL, GRAB_BROKEN, + COMPOSITED_CHANGED, LAST_SIGNAL }; @@ -787,6 +788,14 @@ gtk_widget_class_init (GtkWidgetClass *klass) _gtk_marshal_BOOLEAN__BOXED, G_TYPE_BOOLEAN, 1, GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE); + widget_signals[COMPOSITED_CHANGED] = + g_signal_new (I_("composited_changed"), + G_TYPE_FROM_CLASS (gobject_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GtkWidgetClass, composited_changed), + NULL, NULL, + _gtk_marshal_VOID__VOID, + G_TYPE_NONE, 0); /** * GtkWidget::delete-event: @@ -5157,6 +5166,49 @@ gtk_widget_propagate_screen_changed_recurse (GtkWidget *widget, g_object_unref (widget); } +/** + * gtk_widget_is_composited: + * @widget: + * + * Whether @widget can rely on having its alpha channel + * drawn correctly. On X11 this function returns whether a + * compositing manager is running for @widget's screen + * + * Return value: #TRUE if the widget can rely on its alpha + * channel being drawn correctly. + * + * Since: 2.10 + **/ +gboolean +gtk_widget_is_composited (GtkWidget *widget) +{ + g_return_val_if_fail (GTK_IS_WIDGET (widget), FALSE); + + GdkScreen *screen = gtk_widget_get_screen (widget); + + return gdk_screen_is_composited (screen); +} + +static void +propagate_composited_changed (GtkWidget *widget, + gpointer dummy) +{ + if (GTK_IS_CONTAINER (widget)) + { + gtk_container_forall (GTK_CONTAINER (widget), + propagate_composited_changed, + NULL); + } + + g_signal_emit (widget, widget_signals[COMPOSITED_CHANGED], 0); +} + +void +_gtk_widget_propagate_composited_changed (GtkWidget *widget) +{ + propagate_composited_changed (widget, NULL); +} + /** * _gtk_widget_propagate_screen_changed: * @widget: a #GtkWidget diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h index d161bbebb3..7cfc3df5cd 100644 --- a/gtk/gtkwidget.h +++ b/gtk/gtkwidget.h @@ -407,8 +407,9 @@ struct _GtkWidgetClass gboolean (*grab_broken_event) (GtkWidget *widget, GdkEventGrabBroken *event); + void (* composited_changed) (GtkWidget *widget); + /* Padding for future expansion */ - void (*_gtk_reserved3) (void); void (*_gtk_reserved4) (void); void (*_gtk_reserved5) (void); void (*_gtk_reserved6) (void); @@ -738,6 +739,9 @@ GtkTextDirection gtk_widget_get_direction (GtkWidget *widget); void gtk_widget_set_default_direction (GtkTextDirection dir); GtkTextDirection gtk_widget_get_default_direction (void); +/* Compositing manager functionality */ +gboolean gtk_widget_is_composited (GtkWidget *widget); + /* Counterpart to gdk_window_shape_combine_mask. */ void gtk_widget_shape_combine_mask (GtkWidget *widget, @@ -788,6 +792,7 @@ void _gtk_widget_propagate_hierarchy_changed (GtkWidget *widget, GtkWidget *previous_toplevel); void _gtk_widget_propagate_screen_changed (GtkWidget *widget, GdkScreen *previous_screen); +void _gtk_widget_propagate_composited_changed (GtkWidget *widget); GdkColormap* _gtk_widget_peek_colormap (void); diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index d59ff6553f..82cc51dbe0 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -172,6 +172,9 @@ struct _GtkWindowPrivate guint accept_focus : 1; guint focus_on_map : 1; guint deletable : 1; + + guint reset_type_hint : 1; + GdkWindowTypeHint type_hint; }; static void gtk_window_class_init (GtkWindowClass *klass); @@ -279,6 +282,8 @@ static void gtk_window_unrealize_icon (GtkWindow *window); static void gtk_window_notify_keys_changed (GtkWindow *window); static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window); static void gtk_window_free_key_hash (GtkWindow *window); +static void gtk_window_on_composited_changed (GdkScreen *screen, + GtkWindow *window); static GSList *toplevel_list = NULL; static GtkBinClass *parent_class = NULL; @@ -815,6 +820,7 @@ gtk_window_init (GtkWindow *window) priv->accept_focus = TRUE; priv->focus_on_map = TRUE; priv->deletable = TRUE; + priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL; colormap = _gtk_widget_peek_colormap (); if (colormap) @@ -826,6 +832,8 @@ gtk_window_init (GtkWindow *window) gtk_decorated_window_init (window); + g_signal_connect (window->screen, "composited_changed", + G_CALLBACK (gtk_window_on_composited_changed), window); } static void @@ -937,9 +945,11 @@ gtk_window_get_property (GObject *object, GParamSpec *pspec) { GtkWindow *window; + GtkWindowPrivate *priv; window = GTK_WINDOW (object); - + priv = GTK_WINDOW_GET_PRIVATE (window); + switch (prop_id) { GtkWindowGeometryInfo *info; @@ -1000,8 +1010,7 @@ gtk_window_get_property (GObject *object, g_value_set_boolean (value, window->has_toplevel_focus); break; case PROP_TYPE_HINT: - g_value_set_enum (value, - window->type_hint); + g_value_set_enum (value, priv->type_hint); break; case PROP_SKIP_TASKBAR_HINT: g_value_set_boolean (value, @@ -1980,9 +1989,20 @@ void gtk_window_set_type_hint (GtkWindow *window, GdkWindowTypeHint hint) { + GtkWindowPrivate *priv; + g_return_if_fail (GTK_IS_WINDOW (window)); g_return_if_fail (!GTK_WIDGET_VISIBLE (window)); - window->type_hint = hint; + + priv = GTK_WINDOW_GET_PRIVATE (window); + + if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU) + window->type_hint = hint; + else + window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL; + + priv->reset_type_hint = TRUE; + priv->type_hint = hint; } /** @@ -1996,9 +2016,13 @@ gtk_window_set_type_hint (GtkWindow *window, GdkWindowTypeHint gtk_window_get_type_hint (GtkWindow *window) { + GtkWindowPrivate *priv; + g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL); - return window->type_hint; + priv = GTK_WINDOW_GET_PRIVATE (window); + + return priv->type_hint; } /** @@ -3956,6 +3980,12 @@ gtk_window_finalize (GObject *object) window->keys_changed_handler = 0; } + if (window->screen) + { + g_signal_handlers_disconnect_by_func (window->screen, + gtk_window_on_composited_changed, window); + } + G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -4101,6 +4131,17 @@ gtk_window_map (GtkWidget *widget) window->need_default_size = FALSE; window->need_default_position = FALSE; + if (priv->reset_type_hint) + { + /* We should only reset the type hint when the application + * used gtk_window_set_type_hint() to change the hint. + * Some applications use X directly to change the properties; + * in that case, we shouldn't overwrite what they did. + */ + gdk_window_set_type_hint (widget->window, priv->type_hint); + priv->reset_type_hint = FALSE; + } + gdk_window_show (widget->window); if (window->frame) @@ -4312,8 +4353,8 @@ gtk_window_realize (GtkWidget *widget) if (!priv->deletable) gdk_window_set_functions (widget->window, GDK_FUNC_ALL | GDK_FUNC_CLOSE); - gdk_window_set_type_hint (widget->window, window->type_hint); - + gdk_window_set_type_hint (widget->window, priv->type_hint); + if (gtk_window_get_skip_pager_hint (window)) gdk_window_set_skip_pager_hint (widget->window, TRUE); @@ -6866,13 +6907,30 @@ gtk_window_set_screen (GtkWindow *window, window->screen = screen; gtk_widget_reset_rc_styles (widget); if (screen != previous_screen) - _gtk_widget_propagate_screen_changed (widget, previous_screen); + { + g_signal_handlers_disconnect_by_func (previous_screen, + gtk_window_on_composited_changed, window); + g_signal_connect (screen, "composited_changed", + G_CALLBACK (gtk_window_on_composited_changed), window); + + _gtk_widget_propagate_screen_changed (widget, previous_screen); + _gtk_widget_propagate_composited_changed (widget); + } g_object_notify (G_OBJECT (window), "screen"); if (was_mapped) gtk_widget_map (widget); } +static void +gtk_window_on_composited_changed (GdkScreen *screen, + GtkWindow *window) +{ + gtk_widget_queue_draw (GTK_WIDGET (window)); + + _gtk_widget_propagate_composited_changed (GTK_WIDGET (window)); +} + static GdkScreen * gtk_window_check_screen (GtkWindow *window) { diff --git a/gtk/gtkwindow.h b/gtk/gtkwindow.h index 884b250f5d..f022bb9eb1 100644 --- a/gtk/gtkwindow.h +++ b/gtk/gtkwindow.h @@ -94,7 +94,9 @@ struct _GtkWindow guint maximize_initially : 1; guint decorated : 1; - guint type_hint : 3; /* GdkWindowTypeHint */ + guint type_hint : 3; /* GdkWindowTypeHint if the hint is one of the original eight. If not, then + * it contains GDK_WINDOW_TYPE_HINT_NORMAL + */ guint gravity : 5; /* GdkGravity */ guint is_active : 1; diff --git a/tests/testgtk.c b/tests/testgtk.c index dec2cad874..080eec9c14 100644 --- a/tests/testgtk.c +++ b/tests/testgtk.c @@ -170,7 +170,8 @@ on_alpha_window_expose (GtkWidget *widget, widget->allocation.height / 2, radius * 1.33); - if (gdk_screen_get_rgba_colormap (gtk_widget_get_screen (widget))) + if (gdk_screen_get_rgba_colormap (gtk_widget_get_screen (widget)) && + gtk_widget_is_composited (widget)) cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.0); /* transparent */ else cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* opaque white */ @@ -354,6 +355,18 @@ on_alpha_screen_changed (GtkWidget *widget, gtk_widget_set_colormap (widget, colormap); } +static void +on_composited_changed (GtkWidget *window, + GtkLabel *label) +{ + gboolean is_composited = gtk_widget_is_composited (window); + + if (is_composited) + gtk_label_set_text (label, "Composited"); + else + gtk_label_set_text (label, "Not composited"); +} + void create_alpha_window (GtkWidget *widget) { @@ -379,22 +392,26 @@ create_alpha_window (GtkWidget *widget) TRUE, TRUE, 0); label = gtk_label_new (NULL); - gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (vbox), build_alpha_widgets (), TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (vbox), build_alpha_drawing (), TRUE, TRUE, 0); - on_alpha_screen_changed (window, NULL, label); g_signal_connect (window, "screen-changed", G_CALLBACK (on_alpha_screen_changed), label); + label = gtk_label_new (NULL); + gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0); + on_composited_changed (window, GTK_LABEL (label)); + g_signal_connect (window, "composited_changed", G_CALLBACK (on_composited_changed), label); + + gtk_box_pack_start (GTK_BOX (vbox), build_alpha_widgets (), TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (vbox), build_alpha_drawing (), TRUE, TRUE, 0); + g_signal_connect (window, "destroy", G_CALLBACK (gtk_widget_destroyed), &window); g_signal_connect (window, "response", G_CALLBACK (gtk_widget_destroy), - NULL); + NULL); } if (!GTK_WIDGET_VISIBLE (window)) -- 2.30.2